package ltd.nullpointer.frontend.facade;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.boot2.core.utils.BeanUtils;
import com.boot2.core.utils.HttpsClient;
import com.boot2.core.utils.ThreadPoolTaskExecutorUtil;
import lombok.extern.apachecommons.CommonsLog;
import ltd.nullpointer.frontend.constant.DeviceConstant;
import ltd.nullpointer.frontend.dao.GprsModuleDao;
import ltd.nullpointer.frontend.dao.SensorDataDao;
import ltd.nullpointer.frontend.model.dto.up.SensorData1BDto;
import ltd.nullpointer.frontend.model.entity.SensorRainData;
import ltd.nullpointer.frontend.model.entity.up.GprsModule;
import ltd.nullpointer.frontend.model.entity.up.ModuleHeartBeatUp;
import ltd.nullpointer.frontend.model.entity.up.SensorData;
import ltd.nullpointer.frontend.service.NpAtrributeKvService;
import ltd.nullpointer.frontend.service.SensorDataService;
import ltd.nullpointer.frontend.service.SensorRainDataService;
import ltd.nullpointer.tcp.server.conf.ThingsNpProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * @author zhangweilin
 * @Description: 专门处理上报的消息实体
 * @date 2019/12/19
 */
@Component
@CommonsLog
public class SensorMessageUpFacade {

    @Autowired
    SensorDataDao sensorDataDao;

    @Autowired
    SensorDataService sensorDataService;

    @Autowired
    SensorRainDataService sensorRainDataService;

    @Autowired
    NpAtrributeKvService npAtrributeKvService;

    @Autowired
    ThingsNpProperties thingsNpProperties;

    @Autowired
    GprsModuleDao gprsModuleDao;

    ThreadPoolTaskExecutor threadPoolTaskExecutorUtil = ThreadPoolTaskExecutorUtil.createThreadPoolTaskExecutor();


//
    @Async
    public void handSensorData1BDto(SensorData1BDto sensorData1BDto) {

        List<SensorData1BDto.Data> dataList = sensorData1BDto.getDataList();
        SensorRainData sensorRainData = new SensorRainData();
        BeanUtils.copyProperties(sensorData1BDto, sensorRainData);

        //入库
        sensorRainData.setCreateTime();
        sensorRainDataService.saveSensorRainData(sensorRainData,dataList);

        String token = npAtrributeKvService.getTokenBySensorNo(sensorData1BDto.getSensorNo());
        String attributesUrl = thingsNpProperties.getBaseHttpUrl() + String.format("%s/attributes", token);
//        String telemetryUrl = thingsNpProperties.getBaseHttpUrl() + String.format("%s/telemetry", token);
        //客户端属性转发tb
        String attributesJson = JSONObject.toJSONString(sensorRainData, SerializerFeature.WriteDateUseDateFormat);
        threadPoolTaskExecutorUtil.submit(() -> {
            HttpsClient.postJson(attributesUrl, attributesJson);
        });

//        //遥测数据转发tb
//        for (SensorData1BDto.Data data : dataList) {
//            String telemetryJson = JSONObject.toJSONString(data, SerializerFeature.WriteDateUseDateFormat);
//            threadPoolTaskExecutorUtil.submit(() -> {
//                HttpsClient.postJson(telemetryUrl, telemetryJson);
//            });
//        }
    }

    @Async
    public void handMultiSensorData(SensorData1BDto sensorData1BDto) {

        List<SensorData1BDto.Data> dataList = sensorData1BDto.getDataList();
        for(SensorData1BDto.Data data: dataList) {
            SensorData sensorData = new SensorData();
//            sensorData.setSensorNo(sensorData1BDto.getSensorNo());
//            sensorData.setSensorSelfNo(sensorData1BDto.getSensorSelfNo());
//            sensorData.setModel(sensorData1BDto.getModel());
//            sensorData.setMeasuringDate(data.getMeasuringDate());
//
//            sensorData.setTemp(data.getTemp());
//            sensorData.setMeasurement(data.getMeasurement());
//            sensorData.setDeviation(data.getDeviation());
//            sensorData.setStrainFre(data.getStrainFre());
//            sensorData.setComFre(data.getComFre());
//            sensorData.setUnit(sensorData1BDto.getUnit());
//            sensorData.setType(sensorData1BDto.getType());

            BeanUtils.copyProperties(sensorData1BDto,sensorData);
            sensorData.setMeasuringTime(data.getMeasuringDate());
            sensorData.setCreateTime();
            //在此处利用公式修正测量值
            sensorData.setOriginalMeasure(data.getMeasurement());
            Map<String, Double> allAttributeKv = npAtrributeKvService.selectAllAttributeKv(sensorData.getSensorNo());
            Double initialValue = allAttributeKv.get("initial_value") == null ? 0.0 : allAttributeKv.get("initial_value");
            Double height = allAttributeKv.get("height") == null ? 0.0 : allAttributeKv.get("height");
            Double depth = allAttributeKv.get("depth") == null ? 0.0 : allAttributeKv.get("depth");
            Double ratio = allAttributeKv.get("ratio") == null ? 1.0 : allAttributeKv.get("ratio");
            Double controlFlag = allAttributeKv.get("control_flag");
            if (controlFlag != null && controlFlag == 1) {
                Double height2 = height - depth + ratio * (sensorData.getMeasurement().doubleValue() - initialValue);
                sensorData.setMeasurement(new BigDecimal(height2));
            }
            sensorDataService.save(sensorData);
        }
    }

    @Async
    public void handSensorData(SensorData sensorData) {
//        sensorRainDataService.saveSensorData(sensorData);
        //在此处利用公式修正测量值
        sensorData.setOriginalMeasure(sensorData.getMeasurement());
        sensorData.setMeasuringDate(sensorData.getMeasuringTime());
        Map<String, Double> allAttributeKv = npAtrributeKvService.selectAllAttributeKv(sensorData.getSensorNo());
        Double initialValue = allAttributeKv.get("initial_value") == null ? 0.0 : allAttributeKv.get("initial_value");
        Double height = allAttributeKv.get("height") == null ? 0.0 : allAttributeKv.get("height");
        Double depth = allAttributeKv.get("depth") == null ? 0.0 : allAttributeKv.get("depth");
        Double ratio = allAttributeKv.get("ratio") == null ? 1.0 : allAttributeKv.get("ratio");
        Double controlFlag = allAttributeKv.get("control_flag");
        if (controlFlag != null && controlFlag == 1) {
            Double height2 = height - depth + ratio * (sensorData.getMeasurement().doubleValue() - initialValue);
            sensorData.setMeasurement(new BigDecimal(height2));
        }

        SensorData sensorData2 = new SensorData();
        sensorData2.setSensorNo(sensorData.getSensorNo());
        sensorData2.setMeasuringTime(sensorData.getMeasuringTime());
        List<SensorData> oldSensorDatas = sensorDataDao.findAll(Example.of(sensorData2));
        if (oldSensorDatas != null && oldSensorDatas.size() > 0) {
            for (SensorData data:oldSensorDatas) {
                BeanUtils.copyProperties(sensorData, data);
                sensorDataDao.saveAndFlush(data);
                sendSensorData(data);
            }
            return;
        }
        sensorDataDao.saveAndFlush(sensorData);
        sendSensorData(sensorData);
    }

    public void sendSensorData(SensorData sensorData) {
        String token = npAtrributeKvService.getTokenBySensorNo(sensorData.getSensorNo());
        String telemetryUrl = thingsNpProperties.getBaseHttpUrl() + String.format("%s/telemetry", token);
        String telemetryJson = JSONObject.toJSONString(sensorData, SerializerFeature.WriteDateUseDateFormat);
        threadPoolTaskExecutorUtil.submit(() -> {
            HttpsClient.postJson(telemetryUrl, telemetryJson);
        });
    }

    public void handleGprsModuleData(ModuleHeartBeatUp moduleHeartBeat, List<String> sensorNoList) {
        if (sensorNoList == null || sensorNoList.isEmpty()) {
            if(DeviceConstant.statonNoSensorNoCache.contains(moduleHeartBeat.getSensorNo() + "==" + "FFFFFFFFFFFFFFFF"))
                return;
            DeviceConstant.statonNoSensorNoCache.add(moduleHeartBeat.getSensorNo() + "==" + "FFFFFFFFFFFFFFFF");
            if (gprsModuleDao.existsByStationNo(moduleHeartBeat.getSensorNo())) {
                log.warn("忽略重复检测数据，StationNo:"+ moduleHeartBeat.getSensorNo() + "SensorNo: ");
                return;
            }
            GprsModule gprsModule = new GprsModule();
            gprsModule.setIdentification(moduleHeartBeat.getIdentification());
            gprsModule.setInterval(moduleHeartBeat.getInterval());
            gprsModule.setTemp(moduleHeartBeat.getTemp());
            gprsModule.setStationNo(moduleHeartBeat.getSensorNo());
            gprsModule.setVoltage(moduleHeartBeat.getVoltage());
            gprsModule.setSensorNo("FFFFFFFFFFFFFFFF");
            gprsModule.setCreateTime();
            gprsModuleDao.saveAndUpdateAndFlush(gprsModule);
        } else {
            for (String sensorNo : sensorNoList) {
                if(DeviceConstant.statonNoSensorNoCache.contains(moduleHeartBeat.getSensorNo() + "==" + sensorNo))
                    continue;
                DeviceConstant.statonNoSensorNoCache.add(moduleHeartBeat.getSensorNo() + "==" + sensorNo);
                boolean exists = gprsModuleDao.existsByStationNoAndSensorNo(moduleHeartBeat.getSensorNo(), sensorNo);
                if (exists) {
                    log.warn("忽略重复检测数据，StationNo:" + moduleHeartBeat.getSensorNo() + " ,SensorNo: " + sensorNoList.get(0));
                    continue;
                }
                GprsModule gprsModule = new GprsModule();
                gprsModule.setIdentification(moduleHeartBeat.getIdentification());
                gprsModule.setInterval(moduleHeartBeat.getInterval());
                gprsModule.setTemp(moduleHeartBeat.getTemp());
                gprsModule.setStationNo(moduleHeartBeat.getSensorNo());
                gprsModule.setVoltage(moduleHeartBeat.getVoltage());
                gprsModule.setSensorNo(sensorNo);
                gprsModule.setCreateTime();
                gprsModuleDao.saveAndUpdateAndFlush(gprsModule);
            }
        }
    }
}
